package velox.jcr.mapper.declarative;

import java.util.Map;

import javax.jcr.Node;
import javax.jcr.RepositoryException;

import org.springframework.beans.BeanWrapper;
import org.springframework.util.Assert;

import velox.jcr.mapper.CascadeType;
import velox.jcr.mapper.LazyBeanFactory;
import velox.jcr.mapper.Loader;
import velox.jcr.mapper.UnitOfWorkHolder;
import velox.jcr.mapper.LazyBeanFactory.LazyBean;

public class ParentMapping implements Mapping {

	private String javaProperty;
	private Loader<String> loader;
	private Class<?> type;
	private CascadeType cascade;

	public ParentMapping(String javaProperty, Class<?> type, Loader<String> loader, CascadeType cascade) {
		this.javaProperty = javaProperty;
		this.type = type;
		this.loader = loader;
		
		Assert.isTrue(! cascade.isRemove() && ! cascade.isRemove(), "create or/and delete cascade is not supported for parent mapping");
		this.cascade = cascade;
	}

	public String getJavaProperty() {
		return javaProperty;
	}

	public void read(Node node, BeanWrapper destination)
			throws RepositoryException {
		destination.setPropertyValue(javaProperty, LazyBeanFactory.create(node.getUUID(), loader, type));
	}

	public void readFromCache(Map<String, Object> cache, BeanWrapper destination) {
		destination.setPropertyValue(javaProperty, LazyBeanFactory.create(((String[]) cache.get(IdMapping.CACHE_KEY))[0], loader, type));
	}

	public void write(Node node, BeanWrapper object, boolean create) throws RepositoryException {
		if (cascade.isPersist()) {
			Object reference = object.getPropertyValue(javaProperty);
			if (reference != null) {
				if (reference instanceof LazyBean && ! ((LazyBean) reference).isLoaded()) return;
				UnitOfWorkHolder.get().getMapperManager().update(reference);
			}
		}
	}

	public void writeToCache(Map<String, Object> cache, BeanWrapper object) {
		// References are not cached
	}

}
